{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Working with tabular data: Pandas\n", "\n", "Pandas provides three things: \n", "1. a new data type specifically designed for tabular data - the `DataFrame`\n", "2. functions for manipulating tabular data\n", "3. IO for tabular data (covered in Week3/Files)\n", "\n", "## Why yet another data type?\n", "Numpy arrays can hold tabular data - 2D matrices. So why do we need another, special data type?\n", "One problem with raw 2D arrays is that they are not self-documenting. What does that mean?\n", "\n", "Take the data from exercise of Week3/Files: We calculated behavioral scores, stored them in a numpy array, and saved the array to a text file:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[0.08656877, 0.26186048],\n", " [0.27081788, 0.48948194],\n", " [0.47072199, 0.65700287],\n", " [0.55996639, 0.81680243],\n", " [0.84880959, 0.98686545],\n", " [0.91045131, 0.99465925]])" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "# load and print matrix\n", "scores = np.loadtxt('dat/pd_scores.txt')\n", "scores" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Do you remember what the data means? What are the individual rows? What are the columns? Imagine this were an analysis on your own data and you'd want to look at the results in 3 months or so.\n", "\n", "There are no labels, so it's hard to know from the data itself what they mean - the data is not \"self-documenting\"\n", "\n", "We can turn this into a DataFrame:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
intial scorefinal score
202309120.0865690.261860
202309130.2708180.489482
202309140.4707220.657003
202309150.5599660.816802
202309160.8488100.986865
202309170.9104510.994659
\n", "
" ], "text/plain": [ " intial score final score\n", "20230912 0.086569 0.261860\n", "20230913 0.270818 0.489482\n", "20230914 0.470722 0.657003\n", "20230915 0.559966 0.816802\n", "20230916 0.848810 0.986865\n", "20230917 0.910451 0.994659" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "# the folder names correspond to the days\n", "days = ['20230912','20230913','20230914','20230915','20230916','20230917']\n", "\n", "# make DataFrame - no need to understand the specifics - I will explain soon what is going on here\n", "# we can easily turn a dictionary into a DataFrame - keys will be column labels, values are the per-row data\n", "# we can also specify row labels - an index.\n", "scores_dict = {'intial score': scores[:, 0], 'final score': scores[:, 1]}\n", "df = pd.DataFrame(scores_dict, index=days)\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can save the data frame as csv and excel, and reload them as a DataFrame, with the labels being preserved:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Unnamed: 0final score
intial score
0.086569202309120.261860
0.270818202309130.489482
0.470722202309140.657003
0.559966202309150.816802
0.848810202309160.986865
0.910451202309170.994659
\n", "
" ], "text/plain": [ " Unnamed: 0 final score\n", "intial score \n", "0.086569 20230912 0.261860\n", "0.270818 20230913 0.489482\n", "0.470722 20230914 0.657003\n", "0.559966 20230915 0.816802\n", "0.848810 20230916 0.986865\n", "0.910451 20230917 0.994659" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.to_csv('dat/scores_df.csv')\n", "df.to_excel('dat/scores_df.xlsx')\n", "\n", "# load data\n", "df_from_file = pd.read_csv('dat/scores_df.csv', index_col=0, )\n", "df_from_file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Creating DataFrames\n", "\n", "We already learned that pandas provides versatile file I/O (csv, excel): [https://pandas.pydata.org/docs/user_guide/io.html]() (see Week3/Files)\n", "\n", "As shown above, a DataFrame can be created from Dictionary.\n", "\n", "Data is 2D and is organized in columns and rows (rows=index). If we do not specify an index during DataFrame creation, it will be generated automatically, as a row numbers:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'column 1': ['a', 'b', 'c'], 'column 2': [10, 20, 30]}\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
column 1column 2
0a10
1b20
2c30
\n", "
" ], "text/plain": [ " column 1 column 2\n", "0 a 10\n", "1 b 20\n", "2 c 30" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d = {'column 1': ['a','b','c'], 'column 2': [10, 20, 30]}\n", "\n", "print(d)\n", "df = pd.DataFrame(d)\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A DataFrame can also be created from a 2D np.array. In that case, we can specify the column names separately:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['20230912', '20230913', '20230914', '20230915', '20230916', '20230917']" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# scores\n", "days" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
initialfinal
202309120.0865690.261860
202309130.2708180.489482
202309140.4707220.657003
202309150.5599660.816802
202309160.8488100.986865
202309170.9104510.994659
\n", "
" ], "text/plain": [ " initial final\n", "20230912 0.086569 0.261860\n", "20230913 0.270818 0.489482\n", "20230914 0.470722 0.657003\n", "20230915 0.559966 0.816802\n", "20230916 0.848810 0.986865\n", "20230917 0.910451 0.994659" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.DataFrame(scores, columns=['initial', 'final'], index=days)\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Accessing data in DataFrames\n", "There are many ways of accessing data in a DataFrame. We cover the basics here.\n", "\n", "More details: [https://pandas.pydata.org/docs/user_guide/indexing.html]()\n", "\n", "### Access columns like a dictionary" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "20230912 0.261860\n", "20230913 0.489482\n", "20230914 0.657003\n", "20230915 0.816802\n", "20230916 0.986865\n", "20230917 0.994659\n", "Name: final, dtype: float64" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df['final'] # df[column_name]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Access rows and columns by name like a 2D dictionary via df.loc\n", "\n", "`df.loc[index_name, column_name]`" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
initialfinal
202309120.0865690.261860
202309130.2708180.489482
202309140.4707220.657003
202309150.5599660.816802
202309160.8488100.986865
202309170.9104510.994659
\n", "
" ], "text/plain": [ " initial final\n", "20230912 0.086569 0.261860\n", "20230913 0.270818 0.489482\n", "20230914 0.470722 0.657003\n", "20230915 0.559966 0.816802\n", "20230916 0.848810 0.986865\n", "20230917 0.910451 0.994659" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "20230912 0.086569\n", "20230913 0.270818\n", "20230914 0.470722\n", "20230915 0.559966\n", "20230916 0.848810\n", "20230917 0.910451\n", "Name: initial, dtype: float64" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.DataFrame(scores, columns=['initial', 'final'], index=days)\n", "display(df)\n", "\n", "df.loc[:, 'initial']\n", "\n", "\n", "# print(\"by row name - all columns: df.loc['20230915']\")\n", "# print(df.loc['20230915'])\n", "\n", "# print(\"this is equivalent to: df.loc['20230915', :]\")\n", "# print(df.loc['20230915', :])\n", "\n", "# print(\"by column name - all rows, one column: df.loc[:, 'initial']\")\n", "# print(df.loc[:, 'initial'])\n", "\n", "# print(\"\\nby row and column name - returns a single cell in the table: df.loc['20230915', 'initial']\")\n", "# print(df.loc['20230915', 'initial'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Access to rows and columns via a numerical index like a 2D array via df.iloc\n", "\n", "`df.iloc[row_number, column_number]`" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "20230912 0.261860\n", "20230913 0.489482\n", "20230914 0.657003\n", "20230915 0.816802\n", "20230916 0.986865\n", "20230917 0.994659\n", "Name: final, dtype: float64\n", "initial 0.270818\n", "final 0.489482\n", "Name: 20230913, dtype: float64\n", "initial 0.270818\n", "final 0.489482\n", "Name: 20230913, dtype: float64\n", "0.6570028706902653\n", "20230912 0.261860\n", "20230913 0.489482\n", "Name: final, dtype: float64\n" ] } ], "source": [ "print(df.iloc[:, 1])\n", "print(df.iloc[1])\n", "print(df.iloc[1, :])\n", "print(df.iloc[2, 1])\n", "print(df.iloc[:2, 1]) # slicing also works" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Mini-Exercise:\n", "Get from the DataFrame below:\n", "- all data from the 'test' column\n", "- all data from the '...' row\n", "- data from the cell at row '...' and column '...'\n", "- the data from the 5th row" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df = pd.DataFrame(...)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Access the underlying data like a numpy array:" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(array([[0.08656877, 0.26186048],\n", " [0.27081788, 0.48948194],\n", " [0.47072199, 0.65700287],\n", " [0.55996639, 0.81680243],\n", " [0.84880959, 0.98686545],\n", " [0.91045131, 0.99465925]]),\n", " numpy.ndarray)" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = df.values\n", "data, type(data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Boolean indexing also works" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
initialfinal
202309120.0865690.261860
202309130.2708180.489482
\n", "
" ], "text/plain": [ " initial final\n", "20230912 0.086569 0.261860\n", "20230913 0.270818 0.489482" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[df['initial'] < 0.4]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can apply boolean indices repeatedly, to filter by different conditions:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nameagescore
0Tim124
1Jim240
2Pim188
3Pip229
4Tom267
\n", "
" ], "text/plain": [ " name age score\n", "0 Tim 12 4\n", "1 Jim 24 0\n", "2 Pim 18 8\n", "3 Pip 22 9\n", "4 Tom 26 7" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nameagescore
1Jim240
3Pip229
4Tom267
\n", "
" ], "text/plain": [ " name age score\n", "1 Jim 24 0\n", "3 Pip 22 9\n", "4 Tom 26 7" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nameagescore
3Pip229
4Tom267
\n", "
" ], "text/plain": [ " name age score\n", "3 Pip 22 9\n", "4 Tom 26 7" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "df = pd.DataFrame({'name': ['Tim', 'Jim', 'Pim', 'Pip', 'Tom'],\n", " 'age': [12, 24, 18, 22, 26],\n", " 'score': [4, 0, 8, 9, 7]})\n", "display(df)\n", "\n", "# first, keep only the old one - age>20 yrs\n", "old_guys = df[df['age']> 20]\n", "display(old_guys)\n", "\n", "# then, filter the dataframe with the old ones, to keep only the high scores - score>4\n", "high_scorer = old_guys[old_guys['score']> 4]\n", "display(high_scorer)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Groupby: Split-apply-combine\n", "A common problem in data analysis is:\n", "\n", "We have an experiment with multiple subjects, and multiple measurements per subject. We'd like to compute the average score for each subject for plotting and statistics.\n", "\n", "For instance:" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "image/png": "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I4GFEEIIIfymywQWr7zyCgMGDCA0NJQJEyawatWqQC+pQ1i5ciXnn38+KSkpGAwGPv/88wbXa5rGo48+SkpKCmFhYcycOZPt27cHZrEdwPz585k0aRJRUVEkJiZy0UUXsXv37ga3keesoQULFjB69Gh7w52pU6eyePFi+/XyfHk2f/58DAYDc+fOtV8mz5nDo48+isFgaPAnKSnJfr08V65lZ2dz3XXXER8fT3h4OGPHjmXjxo3269vyeesSgcWHH37I3LlzeeCBB9i8eTMnnXQSZ599NkeOHAn00gKuoqKCMWPG8NJLL7m8/m9/+xvPPvssL730EuvXrycpKYlZs2bZZ7p0NytWrOD2229n3bp1LFmyhPr6embPnk1FRYX9NvKcNdSnTx+efvppNmzYwIYNGzjttNO48MIL7S9S8ny5t379el577TVGjx7d4HJ5zhoaOXIkR48etf/JyMiwXyfPVVPFxcVMnz6doKAgFi9ezI4dO/jnP/9JbGys/TZt+rxpXcDkyZO1W2+9tcFlw4YN0+69994ArahjArTPPvvM/ner1aolJSVpTz/9tP2y6upqLSYmRnv11VcDsMKOJz8/XwO0FStWaJomz5m3evToob3xxhvyfHlQVlamDRkyRFuyZIl2yimnaHPmzNE0Tf6NNfbII49oY8aMcXmdPFeu3XPPPdqMGTPcXt/Wz1un37Gora1l48aNzJ49u8Hls2fPZs2aNQFaVedw8OBBcnNzGzx3ISEhnHLKKfLc2ZSUlAAQFxcHyHPWHIvFwgcffEBFRQVTp06V58uD22+/nXPPPZczzjijweXynDW1d+9eUlJSGDBgAFdddRUHDhwA5Lly58svv2TixIlcfvnlJCYmMm7cOF5//XX79W39vHX6wKKgoACLxUKvXr0aXN6rVy9yc3MDtKrOQX9+5LlzTdM05s2bx4wZMxg1ahQgz5k7GRkZREZGEhISwq233spnn33GiBEj5Ply44MPPmDTpk3Mnz+/yXXynDU0ZcoU3n77bb7//ntef/11cnNzmTZtGoWFhfJcuXHgwAEWLFjAkCFD+P7777n11lu56667ePvtt4G2/zfW7tNN20rjEeyapvl1LHtXJs+da3fccQfp6en8/PPPTa6T56yhE044gS1btnD8+HE++eQTbrjhBlasWGG/Xp4vh8zMTObMmcMPP/xAaGio29vJc6acffbZ9u/T0tKYOnUqgwYN4q233uLEE08E5LlqzGq1MnHiRJ566ikAxo0bx/bt21mwYAG/+c1v7Ldrq+et0+9YJCQkYDKZmkRZ+fn5TaIx0ZCeWS3PXVN33nknX375JcuWLaNPnz72y+U5cy04OJjBgwczceJE5s+fz5gxY/jXv/4lz5cLGzduJD8/nwkTJmA2mzGbzaxYsYIXXngBs9lsf17kOXMtIiKCtLQ09u7dK/++3EhOTmbEiBENLhs+fLi9oKGtn7dOH1gEBwczYcIElixZ0uDyJUuWMG3atACtqnMYMGAASUlJDZ672tpaVqxY0W2fO03TuOOOO/j000/56aefGDBgQIPr5TnzjqZp1NTUyPPlwumnn05GRgZbtmyx/5k4cSLXXnstW7ZsYeDAgfKceVBTU8POnTtJTk6Wf19uTJ8+vUmZ/J49e+jXrx/QDq9jrU7/7AA++OADLSgoSHvzzTe1HTt2aHPnztUiIiK0Q4cOBXppAVdWVqZt3rxZ27x5swZozz77rLZ582bt8OHDmqZp2tNPP63FxMRon376qZaRkaFdffXVWnJyslZaWhrglQfGH//4Ry0mJkZbvny5dvToUfufyspK+23kOWvovvvu01auXKkdPHhQS09P1+6//37NaDRqP/zwg6Zp8nx5w7kqRNPkOXP25z//WVu+fLl24MABbd26ddp5552nRUVF2V/f5blq6tdff9XMZrP25JNPanv37tXeffddLTw8XFu0aJH9Nm35vHWJwELTNO3ll1/W+vXrpwUHB2vjx4+3lwd2d8uWLdOAJn9uuOEGTdNU2dEjjzyiJSUlaSEhIdrJJ5+sZWRkBHbRAeTquQK0hQsX2m8jz1lDv/vd7+y/ez179tROP/10e1ChafJ8eaNxYCHPmcOVV16pJScna0FBQVpKSop2ySWXaNu3b7dfL8+Va1999ZU2atQoLSQkRBs2bJj22muvNbi+LZ83GZsuhBBCCL/p9DkWQgghhOg4JLAQQgghhN9IYCGEEEIIv5HAQgghhBB+I4GFEEIIIfxGAgshhBBC+I0EFkIIIYTwGwkshBBCCOE3ElgIIYQQwm8ksBBCCCGE30hgIYQQQgi/kcBCCCGEEH7z/5tFExzm4JN0AAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# REMOVE - make dummy data for grouped stats\n", "import matplotlib.pyplot as plt\n", "nb_animals = 10\n", "nb_trials = 6\n", "\n", "scores = np.zeros((nb_animals * nb_trials, 3))\n", "for ani, animal in enumerate(range(nb_animals)):\n", " scores[(ani) * nb_trials:(ani + 1) * nb_trials, 1:] = 2+np.random.randn(nb_trials, 2)/2 + np.array([0.3, 0.8]) + np.random.randn(1) / 2\n", " scores[(ani) * nb_trials:(ani + 1) * nb_trials, 0] = animal\n", "\n", "plt.plot(scores)\n", "\n", "df = pd.DataFrame({'animal': scores[:, 0], 'pre': scores[:,1], 'post': scores[:,2]})\n", "df.to_csv('dat/groupby.csv', index=None)" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
animalprepost
00.02.2119863.107796
10.02.2048712.830730
20.02.5606333.483980
30.01.4764122.801709
40.03.6625193.447005
50.02.5386963.301515
61.01.8672293.484270
71.03.3061503.077195
81.02.7413882.586878
91.01.8741493.264328
101.03.2760062.503612
111.03.3637953.175878
122.03.6451223.871356
132.04.4193453.223414
142.03.1571672.851897
152.03.0752223.591049
162.03.0856894.618074
172.02.7998183.586372
183.02.7174203.483265
193.01.2671452.402146
203.03.4970712.818079
213.01.2074082.662157
223.02.3920432.872839
233.02.8450282.683747
244.01.9638771.633267
254.02.5574041.549594
264.01.1155162.964476
274.01.8303951.952609
284.02.1700952.525734
294.02.5866672.240448
305.02.0451213.573011
315.02.0549613.010360
325.02.0214203.538843
335.01.6267902.702867
345.02.3423042.389883
355.01.8004523.311980
366.00.6416481.322786
376.02.2752060.707293
386.01.0905431.291870
396.01.2893451.976258
406.01.8287721.341221
416.00.9823212.676962
427.03.1793014.185368
437.03.7569863.681570
447.02.0708503.249996
457.02.4056343.025023
467.03.7732973.787543
477.03.3516033.171412
488.02.0754093.820043
498.01.9893372.970652
508.02.4693182.046087
518.02.0548792.514335
528.01.4480872.380560
538.02.5523183.016450
549.02.3695841.889417
559.03.0861232.560759
569.02.0971872.446292
579.01.8574150.800996
589.01.4985171.811201
599.00.7190022.691326
\n", "
" ], "text/plain": [ " animal pre post\n", "0 0.0 2.211986 3.107796\n", "1 0.0 2.204871 2.830730\n", "2 0.0 2.560633 3.483980\n", "3 0.0 1.476412 2.801709\n", "4 0.0 3.662519 3.447005\n", "5 0.0 2.538696 3.301515\n", "6 1.0 1.867229 3.484270\n", "7 1.0 3.306150 3.077195\n", "8 1.0 2.741388 2.586878\n", "9 1.0 1.874149 3.264328\n", "10 1.0 3.276006 2.503612\n", "11 1.0 3.363795 3.175878\n", "12 2.0 3.645122 3.871356\n", "13 2.0 4.419345 3.223414\n", "14 2.0 3.157167 2.851897\n", "15 2.0 3.075222 3.591049\n", "16 2.0 3.085689 4.618074\n", "17 2.0 2.799818 3.586372\n", "18 3.0 2.717420 3.483265\n", "19 3.0 1.267145 2.402146\n", "20 3.0 3.497071 2.818079\n", "21 3.0 1.207408 2.662157\n", "22 3.0 2.392043 2.872839\n", "23 3.0 2.845028 2.683747\n", "24 4.0 1.963877 1.633267\n", "25 4.0 2.557404 1.549594\n", "26 4.0 1.115516 2.964476\n", "27 4.0 1.830395 1.952609\n", "28 4.0 2.170095 2.525734\n", "29 4.0 2.586667 2.240448\n", "30 5.0 2.045121 3.573011\n", "31 5.0 2.054961 3.010360\n", "32 5.0 2.021420 3.538843\n", "33 5.0 1.626790 2.702867\n", "34 5.0 2.342304 2.389883\n", "35 5.0 1.800452 3.311980\n", "36 6.0 0.641648 1.322786\n", "37 6.0 2.275206 0.707293\n", "38 6.0 1.090543 1.291870\n", "39 6.0 1.289345 1.976258\n", "40 6.0 1.828772 1.341221\n", "41 6.0 0.982321 2.676962\n", "42 7.0 3.179301 4.185368\n", "43 7.0 3.756986 3.681570\n", "44 7.0 2.070850 3.249996\n", "45 7.0 2.405634 3.025023\n", "46 7.0 3.773297 3.787543\n", "47 7.0 3.351603 3.171412\n", "48 8.0 2.075409 3.820043\n", "49 8.0 1.989337 2.970652\n", "50 8.0 2.469318 2.046087\n", "51 8.0 2.054879 2.514335\n", "52 8.0 1.448087 2.380560\n", "53 8.0 2.552318 3.016450\n", "54 9.0 2.369584 1.889417\n", "55 9.0 3.086123 2.560759\n", "56 9.0 2.097187 2.446292\n", "57 9.0 1.857415 0.800996\n", "58 9.0 1.498517 1.811201\n", "59 9.0 0.719002 2.691326" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.read_csv('dat/pd_groupby.csv')\n", "df\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "We can solve this using for loops and boolean indexing:\n" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
animalprepost
00.02.2119863.107796
10.02.2048712.830730
20.02.5606333.483980
30.01.4764122.801709
40.03.6625193.447005
50.02.5386963.301515
\n", "
" ], "text/plain": [ " animal pre post\n", "0 0.0 2.211986 3.107796\n", "1 0.0 2.204871 2.830730\n", "2 0.0 2.560633 3.483980\n", "3 0.0 1.476412 2.801709\n", "4 0.0 3.662519 3.447005\n", "5 0.0 2.538696 3.301515" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "animal 0.000000\n", "pre 2.442519\n", "post 3.162122\n", "dtype: float64" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "animal 0.000000\n", "pre 2.442519\n", "post 3.162122\n", "dtype: float64" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "[array([0. , 2.44251943, 3.16212242]),\n", " array([1. , 2.73811958, 3.01536034]),\n", " array([2. , 3.36372726, 3.62369364]),\n", " array([3. , 2.32101921, 2.82037202]),\n", " array([4. , 2.03732544, 2.14435453]),\n", " array([5. , 1.98184125, 3.0878241 ]),\n", " array([6. , 1.35130571, 1.55273191]),\n", " array([7. , 3.08961177, 3.51681884]),\n", " array([8. , 2.09822498, 2.79135462]),\n", " array([9. , 1.9379714 , 2.03333186])]" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# identify all animals\n", "animals = df['animal'].unique()\n", "\n", "# example of boolean indexing\n", "display(df[df['animal']==0.0])\n", "# compute the mean:\n", "display(df[df['animal']==0.0].mean())\n", "display(np.mean(df[df['animal']==0.0], axis=0))\n", "\n", "# loop over all animals\n", "animal_avg = []\n", "for animal in animals:\n", " animal_avg.append(df[df['animal']==animal].mean().values)\n", "animal_avg\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This series of steps is so common, that it has been implemented in pandas: [https://pandas.pydata.org/docs/user_guide/groupby.html]()\n", "\n", "It is applied in two steps: _groupby_ and _aggregate_\n", "1. _groupby_ groups the rows that have the same value in a specific column together\n", "2. _aggregate_ applies a computation that aggregates all data in a group to a single number, like the mean, standard deviation, or max.\n", "\n", "Here is an example of this in action. `df.groupby(column_name)` will produce a new object, that groups all rows with the same value in the specified column into a \"virtual subtable\":" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
animalprepost
00.02.2119863.107796
10.02.2048712.830730
20.02.5606333.483980
30.01.4764122.801709
40.03.6625193.447005
50.02.5386963.301515
\n", "
" ], "text/plain": [ " animal pre post\n", "0 0.0 2.211986 3.107796\n", "1 0.0 2.204871 2.830730\n", "2 0.0 2.560633 3.483980\n", "3 0.0 1.476412 2.801709\n", "4 0.0 3.662519 3.447005\n", "5 0.0 2.538696 3.301515" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grouped = df.groupby('animal')\n", "print(type(grouped))\n", "grouped.get_group(0) # get the subtable for all rows where animal==0.0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Apply the \"mean\" operation to all values in each subtable and make a new table with the aggregate per-group data:" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/var/folders/zr/6ql4dzjx0tq8mpzht_2dwh480000gn/T/ipykernel_3584/1479352327.py:1: FutureWarning: The provided callable is currently using DataFrameGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"mean\" instead.\n", " agg = grouped.aggregate(np.mean)\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
prepost
animal
0.02.4425193.162122
1.02.7381203.015360
2.03.3637273.623694
3.02.3210192.820372
4.02.0373252.144355
5.01.9818413.087824
6.01.3513061.552732
7.03.0896123.516819
8.02.0982252.791355
9.01.9379712.033332
\n", "
" ], "text/plain": [ " pre post\n", "animal \n", "0.0 2.442519 3.162122\n", "1.0 2.738120 3.015360\n", "2.0 3.363727 3.623694\n", "3.0 2.321019 2.820372\n", "4.0 2.037325 2.144355\n", "5.0 1.981841 3.087824\n", "6.0 1.351306 1.552732\n", "7.0 3.089612 3.516819\n", "8.0 2.098225 2.791355\n", "9.0 1.937971 2.033332" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "agg = grouped.aggregate(np.mean)\n", "agg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plot the result:" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "image/png": "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qxRgqampSutoOwcsJycHixcvxvLlyyGTyeDk5IRly5ZhypQpJjflQaFQYOLEifjtt98gEonw888/Y8KECcZulsFxoLEKqegcsOPHj+PkyZPIyMhQWqfoHLBu3bqhY8eOGs8BO3z4MCZNmiRMiB02bBhWr14NLy8vnb+W8pLJZHjvvfewadMmWFhY4Pfff4dYLDZ2s4yCA41VCJrMAXN2dkaXLl2EACvLHLDU1FTMmjULmzdvBgDUrl0ba9aswbBhw3T1UnSqoKAAY8aMwY4dO2BpaYktW7bgnXfeMXazjIYDjZkkfdcBex0RITQ0FLNnz8bz588hEokwbdo0LFmyBC4uLrp4STqXl5eHd955B3///Tesra3x559/Yvjw4cZullFxoDGToOkcsKJTKMpaB+x1t2/fxqRJkxAZGQkAaN26NdavX48333yz3NvWl5ycHAQGBmL//v2wtbVFREQEBg4caOxmGR0HGjMKbeaAFT4aNGig07lU+fn5+Pbbb7F06VLk5eXB3t4eX375JWbOnGnSdxHLzs7GkCFDcPToUdjb22P37t3o06ePsZtlEjjQmN6RhveC1HcdsKJOnjyJCRMmIC4uDgAQEBCAdevWoV69enrbpy5kZmZi4MCBOHXqFJycnLB3715069bN2M0yGRxoTOd0OQdM19LS0vDxxx/j119/BQBUr14dq1atwqhRo0x+Jn1aWhr69++Pc+fOwdXVFfv37y/2XgSVFQcaKzdN54D5+fkJY2CGrAMGvArZP//8EzNnzhSKLn7wwQf49ttvUbVqVYO1o6yePn2Kvn374sqVK6hatSoOHTqEdu3aGbtZGpHL5Qa7czpf+sS0pum9IHv06EGff/45HT58WO29IA0lISGBBgwYILStadOmdPz4caO1R1vJycnUokULAkDVq1enmJgYYzdJY+Hh4eTl5aX02fDy8qLw8PBin8P35dQCB5r29HEvSEMoKCig5cuXC+21sbGhL7/80iTapqmHDx9S48aNCQB5enpSXFycsZuksfDwcBKJRCqfFZFIRCKRqNhQ40DTAgda6TIzM2n//v30ySefUNeuXcnGxkblQ1m1alUaNmwYrVixgi5cuEAFBQXGbraSc+fOUZs2bYT2du/enW7evGnsZmnl/v37VL9+fQJAderUofj4eGM3SWMymUzlyOz1UPP29iaZTKbyXA40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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "\n", "x = np.zeros_like(agg.values).T + [[0], [1]]\n", "y = agg.values.T\n", "\n", "plt.figure(figsize=(3, 6))\n", "plt.plot(x, y, 'o-k')\n", "plt.xticks([0, 1], labels=agg.columns)\n", "plt.ylabel('Score')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Example: Connectomics\n", "The connectome of the (female) fly brain was recently published.\n", "\n", "It can be accessed usign a beautiful web interface and user friendly web site: [https://codex.flywire.ai]().\n", "\n", "The web site is great for exploring the fly brain, but clicking around in a web browser has limitations in terms of the reproducibility and scale of an analysis.\n", "\n", "Therefore, the data was made availabel as a set of tables that can be loaded and processed with pandas.\n", "\n", "In the exercise, we will use pandas to answer neuroscience questions about the fly brain - here is a brief introduction to the data:\n", "\n", "There are three main tables:\n", "- connections - connections between cells\n", "- classification - cell classes (afferent, intrinsic, efferent), ...\n", "- (labels - human annotations of cell types)\n", "\n", "Each neuron has a unique identifier, the root_id. The root_id can be used to track neurons across the different tables.\n", "For instance, to find all neurons of a specific types, and then find their inputs or outputs." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Classifications and connections\n", "The classification table has basic information about each of the 130k neurons in the fly brain: the cell_type, side of the brain, position in the brain etc." ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
root_idflowsuper_classclasssub_classcell_typehemibrain_typehemilineagesidenerve
0720575940627005443intrinsicopticL1-5NaNL4NaNNaNrightNaN
1720575940615995398intrinsicopticL1-5NaNL4NaNNaNrightNaN
2720575940621762567afferentascendingANNaNNaNNaNNaNrightCV
3720575940624384007afferentsensoryolfactoryNaNNaNORN_VA1vNaNleftAN
4720575940614422540intrinsiccentralNaNNaNNaNAOTU032,AOTU034LALa1_posteriorrightNaN
.................................
127974720575940621500404intrinsicvisual_projectionNaNNaNNaNLLPC1,LLPC2a,LLPC2b,LLPC2c,LLPC2d,LLPC3NaNrightNaN
127975720575940651646966intrinsiccentralNaNNaNNaNNaNLB0_anteriorcenterNaN
127976720575940630151162intrinsicopticoptic_lobesNaNNaNNaNNaNleftNaN
127977720575940629364731intrinsicopticoptic_lobesNaNNaNNaNNaNrightNaN
127978720575940623859711afferentsensoryvisualNaNR1-6NaNNaNrightNaN
\n", "

127979 rows × 10 columns

\n", "
" ], "text/plain": [ " root_id flow super_class class \\\n", "0 720575940627005443 intrinsic optic L1-5 \n", "1 720575940615995398 intrinsic optic L1-5 \n", "2 720575940621762567 afferent ascending AN \n", "3 720575940624384007 afferent sensory olfactory \n", "4 720575940614422540 intrinsic central NaN \n", "... ... ... ... ... \n", "127974 720575940621500404 intrinsic visual_projection NaN \n", "127975 720575940651646966 intrinsic central NaN \n", "127976 720575940630151162 intrinsic optic optic_lobes \n", "127977 720575940629364731 intrinsic optic optic_lobes \n", "127978 720575940623859711 afferent sensory visual \n", "\n", " sub_class cell_type hemibrain_type \\\n", "0 NaN L4 NaN \n", "1 NaN L4 NaN \n", "2 NaN NaN NaN \n", "3 NaN NaN ORN_VA1v \n", "4 NaN NaN AOTU032,AOTU034 \n", "... ... ... ... \n", "127974 NaN NaN LLPC1,LLPC2a,LLPC2b,LLPC2c,LLPC2d,LLPC3 \n", "127975 NaN NaN NaN \n", "127976 NaN NaN NaN \n", "127977 NaN NaN NaN \n", "127978 NaN R1-6 NaN \n", "\n", " hemilineage side nerve \n", "0 NaN right NaN \n", "1 NaN right NaN \n", "2 NaN right CV \n", "3 NaN left AN \n", "4 LALa1_posterior right NaN \n", "... ... ... ... \n", "127974 NaN right NaN \n", "127975 LB0_anterior center NaN \n", "127976 NaN left NaN \n", "127977 NaN right NaN \n", "127978 NaN right NaN \n", "\n", "[127979 rows x 10 columns]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "classification = pd.read_csv('dat/flywire/classification.csv.gz')\n", "classification" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The connections table contains information about all ~4M synaptic synaptic connections:\n", "- pre_root_id: root_id of the presynaptic neuron, the source\n", "- post_root_id: root_id of the postsynaptic neuron, the target\n", "- syn_count: number of synapses in connection\n", "- nt_type: predicted neurotransmitter neurotransmitter \n", "- neuropil: target neuropil" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pre_root_idpost_root_idneuropilsyn_countnt_type
0720575940596125868720575940608552405LOP_R5ACH
1720575940596125868720575940611348834LOP_R7ACH
2720575940596125868720575940613059993LOP_R5GLUT
3720575940596125868720575940616986553LOP_R5ACH
4720575940596125868720575940620124326LOP_R8ACH
..................
3794610720575940660868737720575940607206786ME_L9GABA
3794611720575940660868737720575940608664873ME_L6GABA
3794612720575940660868737720575940611462242ME_L6GABA
3794613720575940660868737720575940622913063ME_L23GABA
3794614720575940660868737720575940626553546ME_L6ACH
\n", "

3794615 rows × 5 columns

\n", "
" ], "text/plain": [ " pre_root_id post_root_id neuropil syn_count nt_type\n", "0 720575940596125868 720575940608552405 LOP_R 5 ACH\n", "1 720575940596125868 720575940611348834 LOP_R 7 ACH\n", "2 720575940596125868 720575940613059993 LOP_R 5 GLUT\n", "3 720575940596125868 720575940616986553 LOP_R 5 ACH\n", "4 720575940596125868 720575940620124326 LOP_R 8 ACH\n", "... ... ... ... ... ...\n", "3794610 720575940660868737 720575940607206786 ME_L 9 GABA\n", "3794611 720575940660868737 720575940608664873 ME_L 6 GABA\n", "3794612 720575940660868737 720575940611462242 ME_L 6 GABA\n", "3794613 720575940660868737 720575940622913063 ME_L 23 GABA\n", "3794614 720575940660868737 720575940626553546 ME_L 6 ACH\n", "\n", "[3794615 rows x 5 columns]" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "connections = pd.read_csv('dat/flywire/connections.csv.gz')\n", "connections" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example: Find neurons of a specific cell type\n", "LC10a is a cluster of higher-order visual neurons required by Drosophila males to track the female during courtship.\n", "\n", "We can find all LC10a neurons in the fly brain using boolean indexing into the classification table:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
root_idflowsuper_classclasssub_classcell_typehemibrain_typehemilineagesidenerve
3035720575940620720112intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2rightNaN
3691720575940638285109intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2leftNaN
3737720575940614430111intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2rightNaN
4456720575940623082237intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2rightNaN
4544720575940623868853intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2leftNaN
.................................
125773720575940631195217intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2leftNaN
126409720575940631982929intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2leftNaN
126528720575940631983185intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2leftNaN
126843720575940627265223intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2leftNaN
127467720575940610227162intrinsicvisual_projectionNaNNaNLC10aLC10VPNd2leftNaN
\n", "

227 rows × 10 columns

\n", "
" ], "text/plain": [ " root_id flow super_class class sub_class \\\n", "3035 720575940620720112 intrinsic visual_projection NaN NaN \n", "3691 720575940638285109 intrinsic visual_projection NaN NaN \n", "3737 720575940614430111 intrinsic visual_projection NaN NaN \n", "4456 720575940623082237 intrinsic visual_projection NaN NaN \n", "4544 720575940623868853 intrinsic visual_projection NaN NaN \n", "... ... ... ... ... ... \n", "125773 720575940631195217 intrinsic visual_projection NaN NaN \n", "126409 720575940631982929 intrinsic visual_projection NaN NaN \n", "126528 720575940631983185 intrinsic visual_projection NaN NaN \n", "126843 720575940627265223 intrinsic visual_projection NaN NaN \n", "127467 720575940610227162 intrinsic visual_projection NaN NaN \n", "\n", " cell_type hemibrain_type hemilineage side nerve \n", "3035 LC10a LC10 VPNd2 right NaN \n", "3691 LC10a LC10 VPNd2 left NaN \n", "3737 LC10a LC10 VPNd2 right NaN \n", "4456 LC10a LC10 VPNd2 right NaN \n", "4544 LC10a LC10 VPNd2 left NaN \n", "... ... ... ... ... ... \n", "125773 LC10a LC10 VPNd2 left NaN \n", "126409 LC10a LC10 VPNd2 left NaN \n", "126528 LC10a LC10 VPNd2 left NaN \n", "126843 LC10a LC10 VPNd2 left NaN \n", "127467 LC10a LC10 VPNd2 left NaN \n", "\n", "[227 rows x 10 columns]" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "LC10a_neurons = classification[classification['cell_type']=='LC10a']\n", "LC10a_neurons" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example: Find all postsynaptic partners of a given neuron" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "720575940620720112\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pre_root_idpost_root_idneuropilsyn_countnt_type
1309977720575940620720112720575940610389873AOTU_R10ACH
1309978720575940620720112720575940613946783AOTU_R10ACH
1309979720575940620720112720575940614041238AOTU_R9ACH
1309980720575940620720112720575940616012061AOTU_R26ACH
1309981720575940620720112720575940616169629AOTU_R14ACH
1309982720575940620720112720575940616888020AOTU_R7ACH
1309983720575940620720112720575940619453861AOTU_R5ACH
1309984720575940620720112720575940620321158AOTU_R11ACH
1309985720575940620720112720575940621925631AOTU_R7ACH
1309986720575940620720112720575940622538520AOTU_R24ACH
1309987720575940620720112720575940623107509AOTU_R5ACH
1309988720575940620720112720575940626024336AOTU_R5ACH
1309989720575940620720112720575940626643658AOTU_R6ACH
1309990720575940620720112720575940627738640AOTU_R22ACH
1309991720575940620720112720575940628916444AOTU_R13ACH
1309992720575940620720112720575940628972538AOTU_R8ACH
1309993720575940620720112720575940629883971AOTU_R17ACH
1309994720575940620720112720575940631517251AOTU_R31ACH
1309995720575940620720112720575940638668659AOTU_R11ACH
1309996720575940620720112720575940652922529AOTU_R11ACH
\n", "
" ], "text/plain": [ " pre_root_id post_root_id neuropil syn_count nt_type\n", "1309977 720575940620720112 720575940610389873 AOTU_R 10 ACH\n", "1309978 720575940620720112 720575940613946783 AOTU_R 10 ACH\n", "1309979 720575940620720112 720575940614041238 AOTU_R 9 ACH\n", "1309980 720575940620720112 720575940616012061 AOTU_R 26 ACH\n", "1309981 720575940620720112 720575940616169629 AOTU_R 14 ACH\n", "1309982 720575940620720112 720575940616888020 AOTU_R 7 ACH\n", "1309983 720575940620720112 720575940619453861 AOTU_R 5 ACH\n", "1309984 720575940620720112 720575940620321158 AOTU_R 11 ACH\n", "1309985 720575940620720112 720575940621925631 AOTU_R 7 ACH\n", "1309986 720575940620720112 720575940622538520 AOTU_R 24 ACH\n", "1309987 720575940620720112 720575940623107509 AOTU_R 5 ACH\n", "1309988 720575940620720112 720575940626024336 AOTU_R 5 ACH\n", "1309989 720575940620720112 720575940626643658 AOTU_R 6 ACH\n", "1309990 720575940620720112 720575940627738640 AOTU_R 22 ACH\n", "1309991 720575940620720112 720575940628916444 AOTU_R 13 ACH\n", "1309992 720575940620720112 720575940628972538 AOTU_R 8 ACH\n", "1309993 720575940620720112 720575940629883971 AOTU_R 17 ACH\n", "1309994 720575940620720112 720575940631517251 AOTU_R 31 ACH\n", "1309995 720575940620720112 720575940638668659 AOTU_R 11 ACH\n", "1309996 720575940620720112 720575940652922529 AOTU_R 11 ACH" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# select the first LC10a neuron in the list and get it's root_id\n", "pre_root_id = LC10a_neurons.iloc[0]['root_id']\n", "print(pre_root_id)\n", "\n", "# find all downstream targets for that neuron\n", "# that is, all synaptic connections for which our neuron's root_id is the root_id of the pre-synapse\n", "targets = connections[connections['pre_root_id']==pre_root_id]\n", "targets" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernel_info": { "name": "python3" }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.0" }, "nteract": { "version": "0.12.3" }, "vscode": { "interpreter": { "hash": "7ea0ec616133ead53c1908c8f6539f5c0cb9b2f78368e2bb6ab3f847e89ca400" } } }, "nbformat": 4, "nbformat_minor": 4 }